﻿using System.Drawing;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Ruminate.GUI.Framework;
using Ruminate.Utils;
using Color = Microsoft.Xna.Framework.Color;
using Point = Microsoft.Xna.Framework.Point;
using Rectangle = Microsoft.Xna.Framework.Rectangle;

namespace Ruminate.GUI.Content {

    public class BorderRenderer : Renderer {

        public int BorderWidth { get; set; }
        public int StencilBackground { get; set; }
        public int Background { get; set; }

        public BorderRenderer(Texture2D imageMap, int borderWidth, 
            int stencilBackground, int background, RuminateGUI gui) : base(gui, imageMap) {

            BorderWidth = borderWidth;
            StencilBackground = stencilBackground;
            Background = background;
        }

        internal protected override Rectangle BuildSafeArea(Point size) {

            return new Rectangle(BorderWidth, BorderWidth, size.X - 2 * BorderWidth, size.Y - 2 * BorderWidth);
        }

        private static Texture2D RenderLayer(BorderRenderer borderTheme, Rectangle corner,
            Rectangle edge, Point size, GraphicsDevice graphicsDevice) {            

            //Create destination rectangles
            # region Regions to draw to
            //Corners
            var topLeft = new Rectangle(0, 0, borderTheme.BorderWidth, borderTheme.BorderWidth);
            var topRight = new Rectangle(size.X - borderTheme.BorderWidth, 0, borderTheme.BorderWidth, borderTheme.BorderWidth);
            var bottomLeft = new Rectangle(0, size.Y - borderTheme.BorderWidth, borderTheme.BorderWidth, borderTheme.BorderWidth);
            var bottomRight = new Rectangle(size.X - borderTheme.BorderWidth, size.Y - borderTheme.BorderWidth, borderTheme.BorderWidth, borderTheme.BorderWidth);

            //Edges
            var topEdge = new Rectangle(borderTheme.BorderWidth, 0, size.X - (borderTheme.BorderWidth * 2), borderTheme.BorderWidth);            
            var bottomEdge = new Rectangle(borderTheme.BorderWidth, size.Y - borderTheme.BorderWidth, size.X - (borderTheme.BorderWidth * 2), borderTheme.BorderWidth);
            var leftEdge = new Rectangle(0, borderTheme.BorderWidth, borderTheme.BorderWidth, size.Y - (borderTheme.BorderWidth * 2));
            var rightEdge = new Rectangle(size.X - borderTheme.BorderWidth, borderTheme.BorderWidth, borderTheme.BorderWidth, size.Y - (borderTheme.BorderWidth * 2));
            #endregion

            var baker = new TextureBaker(graphicsDevice, size.ToVector2(), RenderState.Fill);

            //Draw Corners 
            #region Draw the Corners
            baker.Draw(
                borderTheme.ImageMap,
                topLeft,
                corner,
                Color.White);
            baker.Draw(
                borderTheme.ImageMap,
                topRight,
                corner,
                Color.White,
                0.0f,
                Vector2.Zero,
                SpriteEffects.FlipHorizontally,
                0);
            baker.Draw(
                borderTheme.ImageMap,
                bottomLeft,
                corner,
                Color.White,
                0.0f,
                Vector2.Zero,
                SpriteEffects.FlipVertically,
                0);
            baker.Draw(
                borderTheme.ImageMap,
                bottomRight,
                corner,
                Color.White,
                0.0f,
                Vector2.Zero,
                SpriteEffects.FlipHorizontally | SpriteEffects.FlipVertically,
                0);
            #endregion

            baker.SetState(RenderState.Fill);

            //Draw Edge
            #region Draw the Edges
            baker.Draw(
                borderTheme.ImageMap,
                topEdge,
                edge,
                Color.White);
            baker.Draw(
                borderTheme.ImageMap,
                bottomEdge,
                edge,
                Color.White,
                0f,
                Vector2.Zero,
                SpriteEffects.FlipVertically,
                0f);

            var temp = baker.GetTexture();

            baker = new TextureBaker(graphicsDevice, new Vector2(edge.Width, edge.Height), RenderState.Fill);
            baker.Draw(borderTheme.ImageMap, Vector2.Zero, edge, Color.White);
            var edgetexture = baker.GetTexture();

            edgetexture = edgetexture.Transform(graphicsDevice, RotateFlipType.Rotate90FlipNone);

            baker = new TextureBaker(graphicsDevice, size.ToVector2(), RenderState.Fill);
            baker.Draw(temp, Vector2.Zero, Color.White);
            baker.Draw(
                edgetexture,
                leftEdge,
                null,
                Color.White,
                0f,
                Vector2.Zero,
                SpriteEffects.FlipHorizontally,
                0f);
            baker.Draw(
                edgetexture,
                rightEdge,
                Color.White);

            #endregion

            return baker.GetTexture();
        }

        public Texture2D Render(Point size) {

            Rectangle                
                oCorner = new Rectangle(0, 0, BorderWidth, BorderWidth),
                oEdge = new Rectangle(BorderWidth, 0, BorderWidth, BorderWidth),
                sCorner = new Rectangle(0, BorderWidth, BorderWidth, BorderWidth),
                sEdge = new Rectangle(BorderWidth, BorderWidth, BorderWidth, BorderWidth),
                sbackground = new Rectangle(0, BorderWidth * 2, StencilBackground, StencilBackground),
                background = new Rectangle(BorderWidth * 2, 0, Background, Background);

            var overlay = RenderLayer(this, oCorner, oEdge, size, GraphicsDevice);
            var stencil = RenderLayer(this, sCorner, sEdge, size, GraphicsDevice);

            //Pull out the stencil for tiling 
            var baker = new TextureBaker(
                GraphicsDevice, 
                new Vector2(StencilBackground, StencilBackground), 
                RenderState.Fill);
            baker.Draw(ImageMap, Vector2.Zero, sbackground, Color.White);
            var sBackground = baker.GetTexture(RotateFlipType.RotateNoneFlipNone);

            //Pull out the background for tiling
            baker = new TextureBaker(
                GraphicsDevice,
                new Vector2(Background, Background),
                RenderState.Fill);
            baker.Draw(ImageMap, Vector2.Zero, background, Color.White);
            var tileAble = baker.GetTexture(RotateFlipType.RotateNoneFlipNone);

            baker = new TextureBaker(GraphicsDevice, size.ToVector2(), RenderState.Fill);

            RenderStencilandOverlay(baker, ImageMap, sBackground, stencil, overlay, size);

            baker.SetState(RenderState.Tile);
            baker.Draw(
                tileAble,
                new Rectangle(
                    BorderWidth,
                    BorderWidth,
                    size.X - (BorderWidth * 2),
                    size.Y - (BorderWidth * 2)),
                new Rectangle(
                    BorderWidth,
                    BorderWidth,
                    size.X - (BorderWidth * 2),
                    size.Y - (BorderWidth * 2)),
                Color.White);

            return baker.GetTexture();
        }
    }
}
